<?php
namespace weixin\mp;

require_once "helper.php";
require_once "access_token.php";

class msg_api {

    private $access_token;
    private $app_id;
    private $data = array();
    private $token = '';
    private $encoding_aes_key = '';
    private $safe_mode = false;

    public function __construct() {
        $this -> access_token = new access_token();

        $app_config = load_config();
 
        $this -> app_id = $app_config -> app_id;
        $this -> token = $app_config -> token;

        if (isset($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
            $this -> safe_mode = true;
        }

        //参数验证
        if ($this -> safe_mode) {
            if (empty($this -> encoding_aes_key) || empty($this -> app_id)) {
                throw new \Exception('缺少参数EncodingAESKey或APP_ID！');
            }
            $this -> encoding_aes_key = $app_config -> encoding_aes_key;
        }

        if ($this -> check_sign()){
            if (isset($_GET["echostr"])) {
                echo $_GET["echostr"];
                exit ;
            } else {
                $this -> init();
            }
		}
    }

    /**
     * 初始化微信推送的数据
     */
    private function init() {
        $xml = file_get_contents("php://input");
        $data = self::xml2data($xml);
        //安全模式 或兼容模式
        if ($this -> safe_mode) {
            if (isset($data['MsgType'])) {
                //兼容模式追加解密后的消息内容
                $data['Decrypt'] = self::extract($data['Encrypt']);
            } else {
                //安全模式
                $data = self::extract($data['Encrypt']);
            }
        }
		file_put_contents('./uploads/error.json', json_encode($data));
        $this -> data = $data;
    }

	function request(){
		return $this->data;
	}


    /**
     * XML数据解码
     * @param  string $xml 原始XML字符串
     * @return array       解码后的数组
     */
    protected static function xml2data($xml) {
        $xml = new \SimpleXMLElement($xml);

        if (!$xml) {
            throw new \Exception('非法XXML');
        }

        $data = array();
        foreach ($xml as $key => $value) {
            $data[$key] = strval($value);
        }
        return $data;
    }

    private function check_sign() {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
 
        $tmpArr = array($this -> token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);

        if ($tmpStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 验证并解密密文数据
     * @param  string $encrypt 密文
     * @return array           解密后的数据
     */
    private static function extract($encrypt) {
        //验证数据签名
        $signature = self::sign($_GET['timestamp'], $_GET['nonce'], $encrypt);
        if ($signature != $_GET['msg_signature']) {
            throw new \Exception('数据签名错误！');
        }

        //消息解密对象
        $msg_crypt = new msg_crypt($this->encoding_aes_key,$this->app_id);

        //解密得到回明文消息
        $decrypt = $msg_crypt -> decrypt($encrypt);

        //返回解密的数据
        return self::xml2data($decrypt);
    }

    /**
     * 加密并生成密文消息数据
     * @param  array $data 获取到的加密的消息数据
     * @return array       生成的加密消息结构
     */
    private static function generate($data) {
        /* 转换数据为XML */
        $xml = new \SimpleXMLElement('<xml></xml>');
        self::data2xml($xml, $data);
        $xml = $xml -> asXML();

        //消息加密对象
        $WechatCrypt = new WechatCrypt(self::$encodingAESKey, self::$appId);

        //加密得到密文消息
        $encrypt = $WechatCrypt -> encrypt($xml);

        //签名
        $nonce = mt_rand(0, 9999999999);
        $signature = self::sign(NOW_TIME, $nonce, $encrypt);

        /* 加密消息基础数据 */
        $data = array('Encrypt' => $encrypt, 'MsgSignature' => $signature, 'TimeStamp' => NOW_TIME, 'Nonce' => $nonce, );

        return $data;
    }

    /**
     * 生成数据签名
     * @param  string $timestamp 时间戳
     * @param  string $nonce     随机数
     * @param  string $encrypt   被签名的数据
     * @return string            SHA1签名
     */
    private static function sign($timestamp, $nonce, $encrypt) {
        $sign = array(self::$token, $timestamp, $nonce, $encrypt);
        sort($sign, SORT_STRING);
        return sha1(implode($sign));
    }

    /**
     * 在请求的企业微信接口后面自动附加token信息
     */
    private function append_token($url) {
        $token = $this -> access_token -> get_access_token();

        if (strrpos($url, "?", 0) > -1) {
            return $url . "&access_token=" . $token;
        } else {
            return $url . "?access_token=" . $token;
        }
    }

    /**
     * 企业主动发送消息给用户
     * @param  [Array like Object] $msg JSON格式的消息体
     */
    public function sendMsgToUser($msg) {
        $url = "https://qyapi.weixin.qq.com/cgi-bin/message/send";

        return http_post($this -> appendToken($url), $msg);
    }

    public function get_app_list() {
        $url = "https://qyapi.weixin.qq.com/cgi-bin/agent/list";

        $return = http_get($this -> appendToken($url));

        return $return;
    }

}
